package org.example.learn.javaagent.threadlocal_link_to_track;

import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.matcher.ElementMatchers;
import net.bytebuddy.utility.JavaModule;

import java.lang.instrument.Instrumentation;

// JavaAgent ThreadLocal 链路追踪
public class Agent {

    // JVM 会首先尝试调用该方法
    public static void premain(String agentArgs, Instrumentation inst){
        System.out.println("ThreadLocal 链路追踪 基于 JavaAgent");

        AgentBuilder agentBuilder = new AgentBuilder.Default();

        AgentBuilder.Transformer transformer = (builder, typeDescription, classLoader, module) -> {
            builder = builder.visit(Advice.to(TrackAdvice.class)
                    .on(ElementMatchers.isMethod()
                            .and(ElementMatchers.any())
                            .and(ElementMatchers.not(ElementMatchers.nameStartsWith("main")))));
            return builder;
        };

        // 按前缀获取类型
        agentBuilder = agentBuilder.type(ElementMatchers.nameStartsWith("org.example.learn.javaagent.threadlocal_link_to_track.run")).transform(transformer);
        // 按名称获取类型
//        agentBuilder = agentBuilder.type(ElementMatchers.named("org.example.learn.javaagent.threadlocal_link_to_track.TestRun")).transform(transformer);

        AgentBuilder.Listener listener = new AgentBuilder.Listener() {
            @Override
            public void onDiscovery(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {

            }

            @Override
            public void onTransformation(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded, DynamicType dynamicType) {
                System.out.println("onTransformation: "+typeDescription);
            }

            @Override
            public void onIgnored(TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, boolean loaded) {

            }

            @Override
            public void onError(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded, Throwable throwable) {

            }

            @Override
            public void onComplete(String typeName, ClassLoader classLoader, JavaModule module, boolean loaded) {

            }
        };

        agentBuilder.with(listener).installOn(inst);
    }

    // JVM 未找到上面方法，将尝试调用该方法
    public static void premain(String agentArgs){
    }
}
